# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""
OEMIcon.py
By: Denver Coneybeare <denver@sleepydragon.org>
Oct 18, 2012
"""

from __future__ import print_function
from __future__ import unicode_literals

from Error import Error
from Icon import Icon

import winapi_constants
from winapi_constants import IMAGE_ICON
from winapi_constants import LR_DEFAULTSIZE
from winapi_constants import LR_SHARED

class OEMIcon(Icon):
    """
    An implementation of Icon where the icon is loaded from one of the Windows
    OEM icons (eg. warning icon).
    """

    ICON_SAMPLE = "ICON_SAMPLE"
    ICON_HAND = "ICON_HAND"
    ICON_QUES = "ICON_QUES"
    ICON_BANG = "ICON_BANG"
    ICON_NOTE = "ICON_NOTE"
    ICON_WINLOGO = "ICON_WINLOGO"
    ICON_WARNING = "ICON_WARNING"
    ICON_ERROR = "ICON_ERROR"
    ICON_INFORMATION = "ICON_INFORMATION"
    ICON_SHIELD = "ICON_SHIELD"

    ALL_ICONS = (
        ICON_SAMPLE,
        ICON_HAND,
        ICON_QUES,
        ICON_BANG,
        ICON_NOTE,
        ICON_WINLOGO,
        ICON_WARNING,
        ICON_ERROR,
        ICON_INFORMATION,
        ICON_SHIELD,
    )

    def __init__(self, id, winapi=None):
        """
        Initializes a new instance of this class.
        *id* must be one if the ICON_ constants defined in this class, which
        specifies the icon to load.
        *winapi* must be the winapi module or a compatible object and will be
        used to perform the low-level operations required by this class; it is
        recommended to simply specify None (the default) in order to use the
        winapi module directly; this argument is primarily intended for use
        during unit testing of this class, and should not normally be explicitly
        specified.
        Raises ValueError if the given ID is not equal to one of the known icon
        IDs.  Raises winnotify.Error if loading the icon with the given ID fails.
        """
        if winapi is None:
            import winapi as winapi_module
            winapi = winapi_module
        self.winapi = winapi

        icon_name = self.icon_name_by_id(id)
        if icon_name is None:
            raise ValueError("unknown icon ID: {}".format(id))
        self.icon_name = icon_name

        icon_name_as_int_resource = winapi.MAKEINTRESOURCE(icon_name)
        handle = winapi.LoadImage(
            hinst=0,
            lpszName=icon_name_as_int_resource,
            uType=IMAGE_ICON,
            cxDesired=0,
            cyDesired=0,
            fuLoad=LR_DEFAULTSIZE|LR_SHARED,
        )
        if handle == 0:
            (errno, message) = self.winapi.get_last_error()
            raise Error("unable to load OEM icon {}: "
                "LoadImage failed: {} ({})".format(id, errno, message))

        Icon.__init__(self, handle)


    @classmethod
    def icon_name_by_id(cls, id):
        """
        Translates one of the ID constants defined in this class to the
        low-level icon name to specify to LoadImage.
        *id* may be any object, and will be converted to the corresponding icon
        name from the winapi_constants module if it compares equal to any of the
        ICON_ constants defined in this class using the == operator.
        Returns the OIC_ constant value from the winapi_constants module for the
        corresponding icon ID; returns None if the given id is now known.
        """
        if id == cls.ICON_SAMPLE:
            icon_name = winapi_constants.OIC_SAMPLE
        elif id == cls.ICON_HAND:
            icon_name = winapi_constants.OIC_HAND
        elif id == cls.ICON_QUES:
            icon_name = winapi_constants.OIC_QUES
        elif id == cls.ICON_BANG:
            icon_name = winapi_constants.OIC_BANG
        elif id == cls.ICON_NOTE:
            icon_name = winapi_constants.OIC_NOTE
        elif id == cls.ICON_WINLOGO:
            icon_name = winapi_constants.OIC_WINLOGO
        elif id == cls.ICON_WARNING:
            icon_name = winapi_constants.OIC_WARNING
        elif id == cls.ICON_ERROR:
            icon_name = winapi_constants.OIC_ERROR
        elif id == cls.ICON_INFORMATION:
            icon_name = winapi_constants.OIC_INFORMATION
        elif id == cls.ICON_SHIELD:
            icon_name = winapi_constants.OIC_SHIELD
        else:
            icon_name = None

        return icon_name
